# -*- coding: utf-8 -*-

#    OriginDB
#    Copyright (C) 2009  Jason Power <power.jg@gmail.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from PyQt4.QtGui import *
from PyQt4.QtCore import *


class ObjectVisual(QGraphicsItem):
	""" People implementing this class must implement paint and boundingRect
	"""
	def __init__(self, parent=None):
		QGraphicsItem.__init__(self, parent)
		
		self.title = ""
		self.details = ""
		
		self._children = []
		self._parents = []
		
		self.connections = {}
		
		self.rect = QRectF()
		
		self.width = 100.0
		self.minWidth = 100.0
		self.height = 100.0
		self.minHeight = 100.0
		
		self.titlePadding = 20
		self.detailPaddingSide = 20
		self.detailPaddingTop = 5

		self.penWidth = 1
		
		self.setFlag(QGraphicsItem.ItemIsMovable, True)
		
		self.setZValue(10)
		
		self.brush = QBrush(QColor(150, 230, 230))
		self.pen = QPen(QColor(100, 180, 180))
		self.pen.setWidth(self.penWidth)
		
		self.titleFont = QFont("Arial", 12, QFont.Bold)
		self.titleBrush = QBrush(Qt.black)
		self.titlePen = QPen(Qt.black)
		self.titleRect = None
		
		self.detailTextItem = QGraphicsTextItem(self)
		self.detailTextItem.setFont(QFont("Arial", 10))
		self.detailTextItem.setTextWidth(self.width - self.detailPaddingSide*2)
		
		self.calcRect()
	
	def addChild(self, child):
		if child in self._children:
			raise ValueError, "Child already there"
		self._children.append(child)
		
	def addParent(self, parent):
		if parent in self._parents:
			raise ValueError, "Parent already there"
		self._parents.append(parent)
		
	def setTitle(self, title):
		if not title:
			self.title = title
			self.titlePath = None
			self.width = self.minWidth
			return
		
		self.title = title
		path = QPainterPath()
		path.addText(0, 0, self.titleFont, self.title)
		
		self.titleRect = path.boundingRect()
		
		self.width = self.titleRect.width() + self.titlePadding*2
		
		if self.width < self.minWidth:
			self.width = self.minWidth
			
		self.calcRect()
		
	def setDetails(self, details):
		self.details = details
		
		self.detailTextItem.setPlainText(details)
		
		rect = self.detailTextItem.boundingRect()
		
		if rect.width()+self.detailPaddingSide*2 > self.width and rect.width()+self.detailPaddingSide*2 > self.minWidth:
			self.width = rect.width() + self.detailPadding*2
		
		self.height = rect.height() + -self.titleLine.y() + self.detailPaddingTop*2
		
		if self.height < self.minHeight:
			self.height = self.minHeight
		
		self.calcRect()
		
	def addConnection(self, conn):
		self.connections[conn] = None
		
	def removeConnection(self, conn):
		del self.connections[conn]
		
	def itemChange(self, change, value):
		if change == QGraphicsItem.ItemPositionHasChanged:
			self.updateConnections()
		return QGraphicsItem.itemChange(self, change, value)
		
	def updateConnections(self):
		for conn in self.connections.keys():
			conn.calcGeometry()
			
	def cleanChildren(self, wpad, hpad):
		if not self._children:
			return
		for item in self._children:
			item.cleanChildren(wpad, hpad)
			if self.collidesWithItem(item):
				item.moveBy(self.width+wpad, 0)
		item = self._children[0]
		colliding = [i for i in item.collidingItems() if isinstance(i, ObjectVisual)]
		rect = item.boundingRect() | item.childrenBoundingRect()
		totalHeight = 0
		for jtem in colliding:
			rect = jtem.boundingRect() | jtem.childrenBoundingRect()
			totalHeight += rect.height() + hpad
		for jtem in colliding:
			jtem.moveBy(0, -totalHeight)
			rect = jtem.boundingRect() | jtem.childrenBoundingRect()
			totalHeight -= rect.height() - hpad
		for jtem in self._children:
			jtem.moveBy(0, totalHeight/2 + hpad*len(colliding)/2)
		
	def calcRect(self):
		self.rect = QRectF(-self.width/2-self.penWidth/2, -self.height/2 - self.penWidth/2, self.width+self.penWidth/2, self.height+self.penWidth/2)
		self.titleLine = QPointF(-self.width/2+self.titlePadding-10, -self.height/2+self.titlePadding+5)
		self.detailTextItem.setPos(-self.width/2+self.detailPaddingSide, self.titleLine.y() + self.detailPaddingTop)
		self.prepareGeometryChange()
		self.updateConnections()
		
	def boundingRect(self):
		return self.rect
		
	def paint(self, painter, option, widget):		
		painter.setRenderHint(QPainter.Antialiasing, True)
		
		painter.setBrush(self.brush)
		painter.setPen(self.pen)
		rounded = min(self.width, self.height)
		painter.drawRoundedRect(-self.width/2, -self.height/2, self.width, self.height, rounded/5, rounded/5)
		
		if self.title:
			painter.setBrush(self.titleBrush)
			painter.setPen(self.titlePen)
			painter.setFont(self.titleFont)
			painter.drawText(-self.width/2+self.titlePadding, -self.height/2+self.titlePadding, self.title)
			painter.drawLine(self.titleLine.x(), self.titleLine.y(), -self.width/2+self.titlePadding+self.titleRect.width()+10, -self.height/2+self.titlePadding+5)